import io
import os
import string
from docx import Document
import docx
import docx.opc
import docx.opc.exceptions
from numpy import *
from DrissionPage import ChromiumPage
from DrissionPage.errors import *
from ddddocr import DdddOcr
from PIL import Image
import cv2
import numpy as np
from DrissionPage.common import Keys

# 创建DdddOcr对象
ocr = DdddOcr(show_ad=False)
class Util:
    def __init__(self,page:ChromiumPage)-> None:
        self.page = page
    # 读取proxy
    def set_user_agent(self,userAgentPath,encoding)->str:
        # 打开文件，换行读取
        with open(userAgentPath, "r" ,encoding=encoding) as f:
            file = f.readlines()
        item = []
        for agent in file:
            # 以换行符分割，转换为dict对象
            agent = eval(agent.replace('\n',''))
            item.append(agent)
        # 随机选取一个IP
        userAgent = random.choice(item)
        return userAgent
    def login(self,url,username,password)->None:
        # 跳转到登录页面
        self.page.get(url)
        self.page.refresh()
        try:
            self.page.ele('#nodeForm',timeout=2).states.is_displayed
            return
        except ElementNotFoundError:
            pass
        # 定位到账号文本框，获取文本框元素，输入对文本框输入账号
        self.page.ele('#txtUserID').clear()
        self.page.ele('#txtUserID').input(username)
        # 定位到密码文本框并输入密码
        self.page.ele('#txtPwd4temp').clear()
        self.page.ele('#txtPwd4temp').input(password)
        # 验证码
        self.page.ele('#verifyCode').clear()
        src = self.page.ele('#validate_image').src()
        img = Image.open(io.BytesIO(src))
        img.save('captcha.png')
        self.processed_captcha('captcha.png')
        # 读取图片文件
        image_data = Image.open('result.jpg')
        # 识别图片验证码
        yzm = ocr.classification(image_data)
        print(yzm)
        self.page.ele('#verifyCode').input(yzm)
        # 点击登录按钮
        self.page.ele('#ibnlogin').click()
        while True:
            self.page.wait(3)
            try:
                # 跳过按钮
                self.page.ele('xpath=/html/body/div[4]/a[2]',timeout=3).click()
                self.page.wait.load_start()
                break
            except ElementNotFoundError:
                print("验证码错误")
                # 定位到账号文本框，获取文本框元素，输入对文本框输入账号
                self.page.ele('#txtUserID').clear()
                self.page.ele('#txtUserID').input(username)
                # 定位到密码文本框并输入密码
                self.page.ele('#txtPwd4temp').clear()
                self.page.ele('#txtPwd4temp').input(password)
                # 验证码
                src = self.page.ele('#validate_image').src()
                img = Image.open(io.BytesIO(src))
                img.save('captcha.png')
                self.processed_captcha('captcha.png')
                # 读取图片文件
                image_data = Image.open('result.jpg')
                # 识别图片验证码
                yzm = ocr.classification(image_data)
                print(yzm)
                self.page.ele('#verifyCode').input(yzm)
                # 点击登录按钮
                self.page.ele('#ibnlogin').click()
        self.page.wait(2)
    def releses(self,selectFlag,path,startPar,endPar)->None:
        self.page.get_screenshot(path='tmp', name='发布页.jpg', full_page=True)
        print('进入发布页！')
        """获取段落"""
        try:
            # 读取的doc可通过save方法保存
            doc = Document(path)
        except docx.opc.exceptions.PackageNotFoundError:
            print("文件未找到，请检查路径是否正确。",print(path))
            self.quit()
            return False
        startNum =  self.chinese_to_int(startPar)
        endNum =  self.chinese_to_int(endPar)+1
        print(startNum)
        print(endNum)
        self.page.wait(4)
        for i in range(startNum,endNum):
            # 遍历文档中的段落，直到找到第二十九章
            # 下拉选择
            self.page.wait(1)
            self.page.ele('xpath=//*[@id="nodeForm"]/div[2]/div[6]/button[1]',timeout=3).wait.displayed()
            try:
                self.page.ele('xpath=//*[@id="nodeForm"]/div[2]/div[1]/div/select',timeout=3).select.by_value(selectFlag)
            except ElementNotFoundError:
                print('下拉选择找不到！')
                self.quit()
                return False
            # 标题
            title = ''
            # 章节标记
            flag = False
            # 循环章节
            for paragraph in doc.paragraphs:
                self.page.wait.doc_loaded()
                if "第{}章".format(self.conversionString(i)) in paragraph.text:
                    print("title:",paragraph.text)
                    title =paragraph.text
                    flag = True
                    # 标题
                    self.page.ele('xpath=//*[@id="nodeForm"]/div[2]/div[2]/div/input').clear()
                    self.page.ele('xpath=//*[@id="nodeForm"]/div[2]/div[2]/div/input').input(title)
                    continue
                if "第{}章".format(self.conversionString(i+1)) in paragraph.text:
                    # 添加按钮
                    try:
                        self.page.wait.doc_loaded()
                        self.page.wait(1)
                        self.page.ele('xpath=//*[@id="nodeForm"]/div[2]/div[6]/button[1]',timeout=3).click()
                    except NoRectError and ElementNotFoundError:
                        print("添加按钮未找到！")
                        self.quit()
                        return False
                    # 继续添加
                    self.page.wait.doc_loaded()
                    self.page.wait(1)
                    self.page.ele('xpath=//*[@id="layui-layer5"]/div[3]/a[1]').click()
                    try:
                        # 操作频繁
                        self.page.ele('xpath=//*[@id="layui-layer3"]/div[3]/a').click()
                        self.page.wait(4)
                    except:
                        self.page.wait(1)
                    break
                if flag:
                    # 添加内容
                    self.page.ele('#txtarea_content').input(paragraph.text)
                    self.page.actions.key_down(Keys.ENTER)
        
    def quit(self):
        self.page.quit()
        print("退出浏览器")
    @classmethod
    def chinese_to_int(cls,chinese_num:str):
        chinese_num = chinese_num.replace('第','')
        chinese_num =  chinese_num.replace('章','')
        num_map = {
            '零': 0, '一': 1, '二': 2, '两': 2, '三': 3,
            '四': 4, '五': 5, '六': 6, '七': 7, '八': 8,
            '九': 9, '十': 10, '百': 100, '千': 1000, '万': 10000
        }
        val = 0
        unit = 1
        for i in range(len(chinese_num) - 1, -1, -1):
            n = chinese_num[i]
            if n in '十百千万':
                unit = num_map[n]
            else:
                val += num_map[n] * unit
        return val
    @classmethod
    def conversionString(cls,intnumber):
        '''
        把数字转换成中文大写，例如：1->一 ，25->二十五，49->四十九
        Parameters
        ----------
        intnumber : TYPE
            DESCRIPTION.
        Returns
        -------
        TYPE
            DESCRIPTION.
        '''
        numberList = ['零','一','二','三','四','五','六','七','八','九']
        unitList = ["","十","百","千","万",'十万','百万','千万','亿','十亿','百亿','千亿','万亿','兆']
        # 转为字符串 获取传入字符串长度
        strnumber = str(intnumber)
        lennumber = len(strnumber)
        # 如果长度等于1 则直接返回对应的各位数字
        if lennumber == 1:
            return numberList[intnumber]
        # 如果不为一 也就不是个位数 则需要获取相关单位
        string = ''
        for i in range(lennumber):
            # print('第{}次,string值为:{}'.format(i,string))
            if int(strnumber[i]) != 0:
                # 判断万出现的次数 如果多次删除现有的 万 字 防止出现 五十万二万 重复
                for unit in ['万','亿']:
                    if string.count(unit) > 1:
                        print(string.count(unit))
                        string = string.replace(unit, '',1)
                # 获取当前数字对应的汉字 + 单位
                string = string + numberList[int(strnumber[i])]+unitList[lennumber - i - 1]
            # 如果前一位也是零 那么直接跳出循环重新执行 //防止
            elif int(strnumber[i - 1]) == 0:
                    continue
            else:
                # 如果都不是 也就是为 那么则直接加一个零
                string = string+numberList[int(strnumber[i])]
        # 返回值 // rstrip 删除结尾的所有零
        string = string.rstrip('零')
        if(intnumber>=10 and intnumber<20):
            return  string[1:]
        return string
    def processed_captcha(self,image_path):
        # 读取图片
        image = cv2.imread(image_path)

        # 转换为灰度图
        gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)

        # 使用阈值进行二值化
        _, binary = cv2.threshold(gray, 150, 255, cv2.THRESH_BINARY_INV)

        # 如果需要，可以进行形态学操作来平滑图像
        kernel = np.ones((2,2), np.uint8)
        binary = cv2.dilate(binary, kernel, iterations=2)
        binary = cv2.erode(binary, kernel, iterations=2)

        # 寻找轮廓
        contours, _ = cv2.findContours(binary, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)

        # 创建一个与原始图像大小相同的黑色背景图像
        white_bg = np.ones_like(image) * 255

        # 遍历轮廓并绘制
        for contour in contours:
            # 计算轮廓的边界框
            x, y, w, h = cv2.boundingRect(contour)
        
            # 根据需要可以设置最小宽度或高度，去除小轮廓
            if cv2.contourArea(contour) > 100:
            
                # 将原始图像中轮廓内的部分复制到黑色背景图像上
                mask = np.zeros_like(gray)
                cv2.drawContours(mask, [contour], -1, 255, -1)
                white_bg[y:y+h, x:x+w] = image[y:y+h, x:x+w]

        # 保存结果到文件
        cv2.imwrite('result.jpg', white_bg)
    # 设置chrome代理
    @classmethod
    def create_proxy_auth_extension(cls,proxy_host, proxy_port, proxy_username, proxy_password, scheme='http', plugin_path=None):
        # 创建Chrome插件的manifest.json文件内容
        manifest_json = """
        {
            "version": "1.0.0",
            "manifest_version": 2,
            "name": "16YUN Proxy",
            "permissions": [
                "proxy",
                "tabs",
                "unlimitedStorage",
                "storage",
                "<all_urls>",
                "webRequest",
                "webRequestBlocking"
            ],
            "background": {
                "scripts": ["background.js"]
            },
            "minimum_chrome_version":"22.0.0"
        }
        """

        # 创建Chrome插件的background.js文件内容
        background_js = string.Template(
            """
            var config = {
                mode: "fixed_servers",
                rules: {
                    singleProxy: {
                        scheme: "${scheme}",
                        host: "${host}",
                        port: parseInt(${port})
                    },
                    bypassList: ["localhost"]
                }
            };

            chrome.proxy.settings.set({value: config, scope: "regular"}, function() {});

            function callbackFn(details) {
                return {
                    authCredentials: {
                        username: "${username}",
                        password: "${password}"
                    }
                };
            }

            chrome.webRequest.onAuthRequired.addListener(
                callbackFn,
                {urls: ["<all_urls>"]},
                ['blocking']
            );
            """
        ).substitute(
            host=proxy_host,
            port=proxy_port,
            username=proxy_username,
            password=proxy_password,
            scheme=scheme,
        )

        # 创建插件目录并写入manifest.json和background.js文件
        os.makedirs(plugin_path, exist_ok=True)
        with open(os.path.join(plugin_path, "manifest.json"), "w+") as f:
            f.write(manifest_json)
        with open(os.path.join(plugin_path, "background.js"), "w+") as f:
            f.write(background_js)
        
        return os.path.join(plugin_path)